/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bean;

import game.Card;
import game.Table;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import org.icefaces.application.PushRenderer;
import other.Costants;
import other.TextModel;

/**
 *
 * @author alessandro
 */
@ManagedBean
@ViewScoped
public class TableBean implements Serializable {

    boolean full;
    boolean tableExist;
    @ManagedProperty(value = "#{messageBean}")
    private MessageBean messageBean;
    @ManagedProperty(value = "#{tablesManager}")
    private TablesManager tablesManager;
    @ManagedProperty(value = "#{chatBean}")
    private ChatBean chatBean;
    @ManagedProperty(value = "#{userManager}")
    private UserManager userManager;
    private String player1Name;
    private String player1Avatar;
    private String player1Cards;
    private String player1Table;
    private String player2Name;
    private String player2Avatar;
    private String player2Cards;
    private String player2Table;
    private String player3Name;
    private String player3Avatar;
    private String player3Cards;
    private String player3Table;
    private String player4Name;
    private String player4Avatar;
    private String player4Cards;
    private String player4Table;
    private String message;
    ArrayList<String> cardsPlayer;

    private boolean userIsPlaying;

    //chat
    private ArrayList<TextModel> textList = new ArrayList<TextModel>();
    private String messageChat;
    
    public TableBean() {
        PushRenderer.addCurrentView(Costants.PUSH_TABLE);
        player1Avatar = Costants.AVATAR_NONE;
        player2Avatar = Costants.AVATAR_NONE;
        player3Avatar = Costants.AVATAR_NONE;
        player4Avatar = Costants.AVATAR_NONE;
        player1Name = "-";
        player2Name = "-";
        player3Name = "-";
        player4Name = "-";
        player1Cards = Costants.ADDRESS_EMPTY;
        player2Cards = Costants.ADDRESS_EMPTY;
        player3Cards = Costants.ADDRESS_EMPTY;
        player4Cards = Costants.ADDRESS_EMPTY;
        cardsPlayer = new ArrayList<String>();
        //message = tablesManager.getTableByUser(userManager.getUsername()).getMessage();
        //userIsPlaying =  tablesManager.getTableByUser(userManager.getUsername()).isPlaying(userManager.getUsername());
    }

    /* GETTERS AND SETTERS */

    public ArrayList<TextModel> getTextList() {
        ArrayList<TextModel> textListO = new ArrayList<TextModel>();
        textListO = messageBean.messagesChatOfTable(tablesManager.getTableByUser(userManager.getUsername()).getName());
        if(textListO != null) {
            return textListO;
        } else {
            return new ArrayList<TextModel>();
        }
        
    }
    public String getMessageChat() {
        return messageChat;
    }
    public void setMessageChat(String messageChat) {
        this.messageChat = messageChat;
    }
    public MessageBean getMessageBean() {
        return messageBean;
    }
    public void setMessageBean(MessageBean messageBean) {
        this.messageBean = messageBean;
    }
    public void setTextList(ArrayList<TextModel> textList) {
        this.textList = textList;
    }
    public ChatBean getChatBean() {
        return chatBean;
    }
    public String getMessage() {
        message = tablesManager.getTableByUser(userManager.getUsername()).getMessage();
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public boolean isTableExist() {
        tableExist = tablesManager.tableExist(userManager.getUsername());
        if(!tableExist) {
            userManager.setState(Costants.CHATTING);
        }
        return tableExist;
    }
    public void setTableExist(boolean tableExist) {
        this.tableExist = tableExist;
    }
    public void setChatBean(ChatBean chatBean) {
        this.chatBean = chatBean;
    }
    public boolean isUserIsPlaying() {
        userIsPlaying =  tablesManager.getTableByUser(userManager.getUsername()).isPlaying(userManager.getUsername());
        return userIsPlaying;
    }
    public void setUserIsPlaying(boolean userIsPlaying) {
        this.userIsPlaying = userIsPlaying;
    }
    public String getPlayer1Avatar() {
        return player1Avatar;
    }
    public void setPlayer1Avatar(String player1Avatar) {
        this.player1Avatar = player1Avatar;
    }
    public String getPlayer1Name() {
        this.setPlayers();
        return player1Name;
    }
    public void setPlayer1Name(String player1Name) {
        this.player1Name = player1Name;
    }
    public String getPlayer2Avatar() {
        return player2Avatar;
    }
    public void setPlayer2Avatar(String player2Avatar) {
        this.player2Avatar = player2Avatar;
    }
    public String getPlayer2Name() {
        return player2Name;
    }
    public void setPlayer2Name(String player2Name) {
        this.player2Name = player2Name;
    }
    public String getPlayer3Avatar() {
        return player3Avatar;
    }
    public void setPlayer3Avatar(String player3Avatar) {
        this.player3Avatar = player3Avatar;
    }
    public String getPlayer3Name() {
        return player3Name;
    }
    public void setPlayer3Name(String player3Name) {
        this.player3Name = player3Name;
    }
    public String getPlayer4Avatar() {
        return player4Avatar;
    }
    public void setPlayer4Avatar(String player4Avatar) {
        this.player4Avatar = player4Avatar;
    }
    public String getPlayer4Name() {
        return player4Name;
    }
    public void setPlayer4Name(String player4Name) {
        this.player4Name = player4Name;
    }
    public String getPlayer1Table() {
        return player1Table;
    }
    public void setPlayer1Table(String player1Table) {
        this.player1Table = player1Table;
    }
    public String getPlayer2Table() {
        return player2Table;
    }
    public void setPlayer2Table(String player2Table) {
        this.player2Table = player2Table;
    }
    public String getPlayer3Table() {
        return player3Table;
    }
    public void setPlayer3Table(String player3Table) {
        this.player3Table = player3Table;
    }
    public String getPlayer4Table() {
        return player4Table;
    }
    public void setPlayer4Table(String player4Table) {
        this.player4Table = player4Table;
    }
    public ArrayList<String> getCardsPlayer() {
        return cardsPlayer;
    }
    public void setCardsPlayer(ArrayList<String> cardsPlayer) {
        this.cardsPlayer = cardsPlayer;
    }
    public UserManager getUserManager() {
        return userManager;
    }
    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }
    public boolean isFull() {
        full = false;
        try {
        full = tablesManager.getTableByUser(userManager.getUsername()).isFull();
        } catch (Exception e) {
            return false;
        }
        return full;
    }
    public void setFull(boolean full) {
        this.full = full;
    }
    public TablesManager getTablesManager() {
        return tablesManager;
    }
    public String getPlayer1Cards() {
        return player1Cards;
    }
    public void setPlayer1Cards(String player1Cards) {
        this.player1Cards = player1Cards;
    }
    public String getPlayer2Cards() {
        return player2Cards;
    }
    public void setPlayer2Cards(String player2Cards) {
        this.player2Cards = player2Cards;
    }
    public String getPlayer3Cards() {
        return player3Cards;
    }
    public void setPlayer3Cards(String player3Cards) {
        this.player3Cards = player3Cards;
    }
    public String getPlayer4Cards() {
        return player4Cards;
    }
    public void setPlayer4Cards(String player4Cards) {
        this.player4Cards = player4Cards;
    }
    public boolean isStarted() {
        if(tablesManager.getTableByUser(userManager.getUsername()) != null) {
            return tablesManager.getTableByUser(userManager.getUsername()).isStarted();
        } else {
            return false;
        }
        
    }
    public void setTablesManager(TablesManager tablesManager) {
        this.tablesManager = tablesManager;
    }

    /* METODI */
    /*metodi chat*/
    public String sendMessage() {
        String user = userManager.getUser().getUser();
        try {
            messageBean.addToList(user, messageChat, tablesManager.getTableByUser(user).getName());
        } catch (Exception e) {
        }
        messageChat = "";
        return null;
    }

    public boolean isFourCards() {
        return tablesManager.getTableByUser(userManager.getUsername()).getDeck().checkFourCards();
    }

    /*controllo per la musica*/
    public boolean isYouLose() {
        int nbots = 0;
        ArrayList<String> winners = tablesManager.getTableByUser(userManager.getUsername()).getWinners();
        for(int i=0; i<winners.size(); i++){
            if(winners.get(i).substring(0, 3).equals(Costants.BOTNAME)) {
                nbots++;
            }

        }
        if(nbots == winners.size() && winners.size() > 0) {
            return true;
        } else
            return false;
    }
    /* controlla se il giocatore può giocare le carte */
    public boolean isPlayerTurn() {
        boolean flag = false;

        String username = userManager.getUsername();
        Table table = tablesManager.getTableByUser(username);
        if(table.getPlayersList().get(table.getDeck().getToken()).equals(username)) {
            flag = true;
        }

        return flag;
    }
    /*metodo che aggiorna la grafica di tutti i componenti*/
    public void setPlayers() {
        List<String> players = new ArrayList<String>();
        int idPlayer = Costants.NULL;
        int token = Costants.NULL;
        players.add("-");
        players.add("-");
        players.add("-");
        players.add("-");

        String viewer = userManager.getUsername();

        if (this.isTableExist()) {
            Table table = tablesManager.getTableByUser(viewer);
            ArrayList<String> playersGame = table.getUserPlaying();

            //inserisco i giocatori nell'array temporaneo
            for (int i = 0; i < playersGame.size(); i++) {
                players.set(i, playersGame.get(i));
                //System.out.println("GIOCATORE GAME " + i + ": " + playersGame.get(i));
            }

            token = table.getDeck().getToken(); //prendo il token

            if (players.contains(viewer)) {
                idPlayer = players.indexOf(viewer); //il giocatore è seduto e / o sta giocando
                if (idPlayer != 3) {
                    for (int j = 0; j < idPlayer+1; j++) { // questa operazione serve a tenere in senso orario i giocatori
                        String playerTemp = players.get(0);
                        //System.out.println("Giocatore SPOSTATO! " + playerTemp);
                        players.remove(0);
                        players.add(playerTemp);
                        if (token == j) {
                            token = players.indexOf(playerTemp);
                        }

                    }
                }
            }

            //setto tutte le immagini per ciascun giocatore seduto / giocante
            for (int i = 0; i < players.size(); i++) {
                //variabili d'appoggio standard
                String tempAvatar = Costants.AVATAR_NONE;
                String tempCards = Costants.ADDRESS_EMPTY;
                String tempTable = Costants.ADDRESS_CARD_EMPTY;
                String tempName = Costants.NICK_EMPTY;

                //nome
                tempName = players.get(i);
                //System.out.println("Giocatore di cui si sta calcolando tutto: "+ tempName);
                //avatar
                if (tempName.startsWith(Costants.BOTNAME)) { // è un bot
                    tempAvatar = Costants.AVATAR_BOT;

                    if (!table.getDeck().checkFourCards() && table.getDeck().getToken() != Costants.NULL && players.get(i).equals(table.getUserPlaying().get(table.getDeck().getToken()))
                            && table.getWinners().isEmpty()) {
                        tempAvatar = tempAvatar + Costants.AVATAR_PLAYING;
                    }
                    tempAvatar = tempAvatar + Costants.PNG;

                } else if (!(tempName.equals(Costants.NICK_EMPTY))) { // è un user
                    tempAvatar = this.getAvatarPlayer(i, token);
                    if (table.getDeck().getToken() != Costants.NULL && players.get(i).equals(table.getUserPlaying().get(table.getDeck().getToken())) &&
                            table.getWinners().isEmpty()) {
                        tempAvatar = tempAvatar + Costants.AVATAR_PLAYING;
                    }

                    tempAvatar = tempAvatar + Costants.PNG;
                    System.out.println("Avatar: "+ tempAvatar);
                }

                //carte e stato
                if (token != Costants.NULL) { // il gioco è iniziato
                    //carte coperte vicino all'avatar
                    int numberCardsHolded = table.getDeck().getCardsNumberStatus(table.getCardsPlayer(tempName), Costants.HOLD_BY_USER);
                    if(numberCardsHolded != 0) {
                        tempCards = Costants.ADDRESS_CARD_OTHERS + numberCardsHolded + Costants.PNG;
                    }
                    
                    //carte sul tavolo
                    Card cardOnTable = table.getCardonTable(tempName);
                    if (cardOnTable != null) {
                        tempTable = Costants.ADDRESS_CARD + cardOnTable.getSeed() + cardOnTable.getNumber() + Costants.PNG;
                    }

                } else if (!tempName.equals(Costants.NICK_EMPTY)) { // il gioco non è iniziato
                    //stato
                    tempCards = Costants.ADDRESS_WAITING;
                }

                switch (i) {
                    case 0:
                        player1Avatar = tempAvatar;
                        player1Name = tempName;
                        player1Cards = tempCards;
                        player1Table = tempTable;
                        break;
                    case 1:
                        player2Avatar = tempAvatar;
                        player2Name = tempName;
                        player2Cards = tempCards;
                        player2Table = tempTable;
                        break;
                    case 2:
                        player3Avatar = tempAvatar;
                        player3Name = tempName;
                        player3Cards = tempCards;
                        player3Table = tempTable;
                        break;
                    case 3:
                        player4Avatar = tempAvatar;
                        player4Name = tempName;
                        player4Cards = tempCards;
                        player4Table = tempTable;
                        break;
                }
            }
            //carte giocabili per il viewer
            if (token != Costants.NULL && table.getUserPlaying().contains(viewer)) {
                cardsPlayer.clear();
                ArrayList<Card> cardsPlayerT = table.getDeck().getCardsFromStatus(table.getCardsPlayer(viewer), Costants.HOLD_BY_USER);
                if (cardsPlayerT != null) {
                    //System.out.println("CARTE GIOCATORE " + viewer);
                    for (int c = 0; c < cardsPlayerT.size(); c++) {
                        //System.out.println("Carta numero: " + c + ": " + cardsPlayerT.get(c).getSeed() + cardsPlayerT.get(c).getNumber());
                        cardsPlayer.add(cardsPlayerT.get(c).getSeed() + cardsPlayerT.get(c).getNumber());
                    }
                }
            }
        }
    }
    /* un user si siede ad un tavolo*/
    public void playOnTable() {
        String username = userManager.getUsername();
        if (this.isTableExist() && !this.isFull()) {
            tablesManager.addPlayer(username);
            userManager.setState(Costants.WAITING);
        }
        PushRenderer.render(Costants.PUSH_TABLE);
        PushRenderer.render(Costants.PUSH_GROUP);
    }
    /* un user esce dal tavolo */
    public String leaveTable() {
        tablesManager.leaveTable(userManager.getUsername());
        PushRenderer.removeCurrentView(Costants.PUSH_TABLE);
        userManager.setState(Costants.CHATTING);
        PushRenderer.render(Costants.PUSH_GROUP);
        PushRenderer.render(Costants.PUSH_TABLE);
        return Costants.CHAT;
    }
    /* l'user gioca una carta */
    public void play(String card) {
        String username = userManager.getUsername();
        Table table = tablesManager.getTableByUser(username);

        /*controlli*/
        table.play(username, card);
    }
    /*trasforma da una stringa ad un url per le immagini*/
    public String fromCardToURL(String card){
        return Costants.ADDRESS_CARD + card + Costants.PNG;
    }
    /*metodo che traduce dalla posizione un avatar*/
    private String getAvatarPlayer(int index, int token) {
        String avatar = "";
        switch(index) {
            case 0:
                avatar = Costants.AVATAR_LEELA;
                break;
            case 1:
                avatar = Costants.AVATAR_PROF;
                break;
            case 2:
                avatar = Costants.AVATAR_FRY;
                break;
            case 3:
                avatar = Costants.AVATAR_PLAYER;
                break;
        }

        

        return avatar;

    }
    /* ritorna true se ci sono 4 carte sul tavolo */
    public boolean isCardsOnTable() {
        Table table = tablesManager.getTableByUser(userManager.getUsername()) ;
        if(table.getDeck().getTableCards().size() == 4) {
            return true;
        } else {
            return false;
        }

    }
    /*calcola il fine del turno*/
    public void endTurn() {
        Table table = tablesManager.getTableByUser(userManager.getUsername());
        table.endTurn();
        if (!(table.getWinners().isEmpty())) {
            ArrayList winners = table.getWinners();
            userManager.setPoints(winners);
            ArrayList<String> loosers = new ArrayList<String>();
            for (int i = 0; i < table.getUserPlaying().size(); i++) {
                for (int j = 0; j < winners.size(); j++) {
                    if (!(table.getUserPlaying().get(i).equals(winners.get(j)))) {
                        loosers.add(table.getUserPlaying().get(i));
                    }
                }
            }
            userManager.removePoints(loosers);
        }


    }
    /*controlla se una carta è giocabile*/
    public boolean playable(String cardP) {

        Card card = new Card(cardP.substring(0,1), Integer.parseInt(cardP.substring(1)));
        card.setState(Costants.HOLD_BY_USER);

        String user = userManager.getUsername();
        Table table = tablesManager.getTableByUser(user);
        boolean flag = false;
        if(table.isStarted() && table.isPlaying(user) && table.getDeck().getToken() == table.getPlayerId(user) && !(table.getDeck().checkFourCards()) ) {
            /* il tavolo è iniziato
             * il giocatore è seduto al tavolo
             * è il turno dl giocatore
             */

            /* regole per la prima mano */
            if (table.getDeck().getRound() == 0) {
                if (card.getSeed().equals(Costants.SEED_F) && card.getNumber() == 2 && table.getDeck().getTableCards().isEmpty()) {
                    /* al primo round se non ci sono carte sul tavolo si deve giocare il 2 di fiori */
                    flag = true;
                } else if (!(table.getDeck().getTableCards().isEmpty())) {
                    /* al primo round non si può rispondere C o P12 salvo non si abbia solo cuori */
                    if (!(card.getSeed().equals(Costants.SEED_P) && card.getNumber() == 12)) {
                        if (card.getSeed().equals(Costants.SEED_C)) {
                            /* può giocare cuori se e solo se ha SOLO cuori (probabilità piccolissima) */
                            int number_hearts = table.getDeck().getNumberCardsFromSeed(table.getCardsPlayer(user), Costants.HOLD_BY_USER, Costants.SEED_C);
                            if (number_hearts == 13) {
                                flag = true;
                            }
                        } else {
                            /*se non è P12 e non è C la carta si può giocare se è uguale al seme oppure se non si hanno carte di quel seme*/
                            if (card.getSeed().equals(table.getDeck().getFirstSeed())) {
                                flag = true;
                            } else {
                                int number_cards_firstseed = table.getDeck().getNumberCardsFromSeed(table.getCardsPlayer(user), Costants.HOLD_BY_USER, table.getDeck().getFirstSeed());
                                if (number_cards_firstseed == 0) {
                                    flag = true;
                                }
                            }
                        }
                    }
                }
            } else {
                /* altri round */
                /*se non ci sono le carte sul tavolo*/
                if(table.getDeck().getTableCards().isEmpty()) {
                    /* controllo se i cuori sono stati rotti */
                    if(table.getDeck().isHeartsBroken()) {
                        flag = true;
                    } else {
                        /* se i cuori non sono stati rotti posso giocare cuori solo se ho solo cuori nel mazzo */
                        int number_cards_hearts = table.getDeck().getNumberCardsFromSeed(table.getCardsPlayer(user), Costants.HOLD_BY_USER, Costants.SEED_C);
                        if ((number_cards_hearts == table.getDeck().getCardsNumberStatus(table.getCardsPlayer(user), Costants.HOLD_BY_USER)) || !(card.getSeed().equals(Costants.SEED_C))) {
                            flag = true;
                        }
                    }
                } else {
                    /* ci sono carte sul tavolo devo giocare solo la carta di quel seme*/
                    if (card.getSeed().equals(table.getDeck().getFirstSeed())) {
                        flag = true;
                    } else {
                        /* se non ho carte di quel seme posso giocare quello che voglio, anche i cuori */
                        int number_cards_firstseed = table.getDeck().getNumberCardsFromSeed(table.getCardsPlayer(user), Costants.HOLD_BY_USER, table.getDeck().getFirstSeed());
                        if (number_cards_firstseed == 0) {
                            flag = true;
                        }
                    }
                }

            }



            /* la carta deve essere in linea con il seme sul tavolo */

            /* il seme non a terra si può giocare solo se non si hanno carte dello stesso seme */
            /* i cuori possono essere attivi non si hanno carte del seme a terra */
        }
        return flag;
    }
}
